/**
 * \file talise_jesd204.c
 * \brief Contains functions to support Talise JESD204b data interface
 *
 * Talise API version: 3.6.0.5
 *
 * Copyright 2015-2017 Analog Devices Inc.
 * Released under the AD9378-AD9379 API license, for more information see the "LICENSE.txt" file in this zip file.
 */

#include "talise_jesd204.h"
#include "talise_reg_addr_macros.h"
#include "talise_arm_macros.h"
#include "talise_hal.h"
#include "talise_user.h"
#include "talise_error.h"
#include "talise.h"

uint32_t TALISE_setupSerializers(taliseDevice_t *device, taliseInit_t *init)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t laneInvert = 0;
    uint8_t activeFramersMask = 0; /* bit per framer to for quick access of valid framers enabled. */
    uint8_t activeLanesEnabled = 0;
    uint8_t activeLanesPowerDown = 0xF;
    uint8_t enPreEmphasisMask = 0x00; /* bit per lane */
    uint8_t preEmp = 0x00; /* same value for all lanes */
    uint8_t txser_div = 0;
    uint8_t i = 0;
    uint8_t obsRxL = 0;
    uint8_t rxL = 0;
    uint32_t rxLaneRate_kHz = 0;
    uint32_t obsRxLaneRate_kHz = 0;
    uint32_t fasterLaneRate_kHz = 0;
    uint32_t slowerLaneRate_kHz = 0;
    uint8_t txser_div_reg = 0;
    uint8_t serAmplitude = 0;
    taliseJesd204bFramerConfig_t *currentFramer = NULL;

    static const uint8_t DUALBANDENABLED = 1;

    /* Determine which framer structures are valid */
    if (device->devStateInfo.profilesValid & RX_PROFILE_VALID)
    {
        switch(init->rx.framerSel)
        {
        case TAL_FRAMER_A:
            activeFramersMask |= 0x01;
            activeLanesEnabled |= init->jesd204Settings.framerA.serializerLanesEnabled;
            laneInvert |= ((init->jesd204Settings.framerA.serializerLanesEnabled) & (init->jesd204Settings.serInvertLanePolarity));
            currentFramer = &init->jesd204Settings.framerA;
            break;
        case TAL_FRAMER_B:
            activeFramersMask |= 0x02;
            activeLanesEnabled |= init->jesd204Settings.framerB.serializerLanesEnabled;
            laneInvert |= ((init->jesd204Settings.framerB.serializerLanesEnabled) & (init->jesd204Settings.serInvertLanePolarity));
            currentFramer = &init->jesd204Settings.framerB;
            break;
        case TAL_FRAMER_A_AND_B:
            activeFramersMask |= 0x03;
            activeLanesEnabled |= init->jesd204Settings.framerA.serializerLanesEnabled;
            activeLanesEnabled |= init->jesd204Settings.framerB.serializerLanesEnabled;
            laneInvert |= ((init->jesd204Settings.framerA.serializerLanesEnabled) & (init->jesd204Settings.serInvertLanePolarity));
            laneInvert |= ((init->jesd204Settings.framerB.serializerLanesEnabled) & (init->jesd204Settings.serInvertLanePolarity));
            currentFramer = &init->jesd204Settings.framerA;
            break;
        default:
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SER_INV_RXFRAMER_SEL, retVal, TALACT_ERR_CHECK_PARAM);
        }

        serAmplitude = init->jesd204Settings.serAmplitude;
        preEmp = init->jesd204Settings.serPreEmphasis;
        enPreEmphasisMask |= (init->jesd204Settings.serPreEmphasis > 0) ? activeLanesEnabled : 0;

        /* TODO: Need error check to make sure that if FRAMER A and B, then make sure each framer has same number of lanes, and M matches */
        for (i = 0; i < 4; i++)
        {
            rxL += ((currentFramer->serializerLanesEnabled >> i) & 0x01);
        }

        if (rxL > 0)
        {
            rxLaneRate_kHz = currentFramer->Np * 10 * init->rx.rxProfile.rxOutputRate_kHz * currentFramer->M / (8 * rxL);
            if ((rxLaneRate_kHz != 0) && ((rxLaneRate_kHz < 768000) || (rxLaneRate_kHz > 12288000)))
            {
                return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SER_INV_LANERATE_PARM, retVal, TALACT_ERR_CHECK_PARAM);
            }
        }

        if ((rxL != 0) &&
            (rxL != 1) &&
            (rxL != 2) &&
            (rxL != 4))
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SER_INV_L_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        }

        if ((currentFramer->Np != 12) &&
            (currentFramer->Np != 16) &&
            (currentFramer->Np != 24))
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SER_INV_NP_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        }

        if ((currentFramer->M == 1) && !(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_INT2_REALIF)
                                    && !(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_DEC2_REALIF)
                                    && !(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_FILTERONLY_REALIF)
                                    && !(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_BYPASS_REALIF))
        {
            return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SER_INV_ZIF_TO_RIF_DATA_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        }

        if ((currentFramer->M == 8) &&
           !(device->devStateInfo.rxDualBandEnabled != DUALBANDENABLED))
        {
            return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SER_INV_DUALBAND_DATA_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        }

        if ((currentFramer->M != 0) &&
            (currentFramer->M != 1) &&
            (currentFramer->M != 2) &&
            (currentFramer->M != 4))
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SER_INV_M_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        }

        if (currentFramer->serializerLanesEnabled > 15)
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SER_INV_LANEEN_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        }
    }

    if (device->devStateInfo.profilesValid & ORX_PROFILE_VALID)
    {
        switch(init->obsRx.framerSel)
        {
            case TAL_FRAMER_A:
                activeFramersMask |= 0x01;
                activeLanesEnabled |= init->jesd204Settings.framerA.serializerLanesEnabled;
                laneInvert |= ((init->jesd204Settings.framerA.serializerLanesEnabled) & (init->jesd204Settings.serInvertLanePolarity));
                currentFramer = &init->jesd204Settings.framerA;
                break;
            case TAL_FRAMER_B:
                activeFramersMask |= 0x02;
                activeLanesEnabled |= init->jesd204Settings.framerB.serializerLanesEnabled;
                laneInvert |= ((init->jesd204Settings.framerB.serializerLanesEnabled) & (init->jesd204Settings.serInvertLanePolarity));
                currentFramer = &init->jesd204Settings.framerB;
                break;
            case TAL_FRAMER_A_AND_B:
                activeFramersMask |= 0x03;
                activeLanesEnabled |= init->jesd204Settings.framerA.serializerLanesEnabled;
                activeLanesEnabled |= init->jesd204Settings.framerB.serializerLanesEnabled;
                laneInvert |= ((init->jesd204Settings.framerA.serializerLanesEnabled) & (init->jesd204Settings.serInvertLanePolarity));
                laneInvert |= ((init->jesd204Settings.framerB.serializerLanesEnabled) & (init->jesd204Settings.serInvertLanePolarity));
                currentFramer = &init->jesd204Settings.framerA;
                break;
            default:
                return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                        TAL_ERR_SER_INV_ORXFRAMER_SEL, retVal, TALACT_ERR_CHECK_PARAM);
        }

        serAmplitude = init->jesd204Settings.serAmplitude;
        preEmp = init->jesd204Settings.serPreEmphasis;
        enPreEmphasisMask |= (init->jesd204Settings.serPreEmphasis > 0) ? activeLanesEnabled : 0;

        /* TODO: Need error check to make sure that if FRAMER A and B, then make sure each framer has same number of lanes, and M matches */
        for(i = 0; i < 4; i++)
        {
            obsRxL += ((currentFramer->serializerLanesEnabled >> i) & 0x01);
        }

        if (obsRxL > 0)
        {
            obsRxLaneRate_kHz = currentFramer->Np * 10 * init->obsRx.orxProfile.orxOutputRate_kHz * currentFramer->M / (8 * obsRxL);
            if ((obsRxLaneRate_kHz != 0) && ((obsRxLaneRate_kHz < 768000) || (obsRxLaneRate_kHz > 12288000)))
            {
                return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                        TAL_ERR_SER_INV_ORX_LANERATE_PARM, retVal, TALACT_ERR_CHECK_PARAM);
            }
        }

        if ((obsRxL != 0) &&
            (obsRxL != 1) &&
            (obsRxL != 2) &&
            (obsRxL != 4))
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_SER_INV_ORX_L_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        }

        if ((currentFramer->Np != 12) &&
            (currentFramer->Np != 16) &&
            (currentFramer->Np != 24))
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_SER_INV_ORX_NP_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        }

        if ((currentFramer->M != 0) &&
            (currentFramer->M != 1) &&
            (currentFramer->M != 2) &&
            (currentFramer->M != 4))
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_SER_INV_ORX_M_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        }

        if (currentFramer->serializerLanesEnabled > 15)
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_SER_INV_ORX_LANEEN_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        }
    }

    if (activeFramersMask == 0x03)
    {
        /* Verify FramerA and FramerB do not share physical lanes */
        if (init->jesd204Settings.framerA.serializerLanesEnabled &
            init->jesd204Settings.framerB.serializerLanesEnabled
           )
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_SER_LANE_CONFLICT_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        }
    }

    if (init->jesd204Settings.serAmplitude > 15)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_SER_INV_AMP_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (init->jesd204Settings.serPreEmphasis > 4)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_SER_INV_PREEMP_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (init->jesd204Settings.serInvertLanePolarity > 15)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_SER_INV_LANEPN_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Calculate needed JESD204 serializer lane rates */
    if ((rxLaneRate_kHz > 0) &&
        (obsRxLaneRate_kHz > 0))
    {
        fasterLaneRate_kHz = (rxLaneRate_kHz >= obsRxLaneRate_kHz) ? (rxLaneRate_kHz) : (obsRxLaneRate_kHz);
        slowerLaneRate_kHz = (rxLaneRate_kHz >= obsRxLaneRate_kHz) ? (obsRxLaneRate_kHz) : (rxLaneRate_kHz);

        /* Verify that lane rates are integer multiples of each other */
        if (fasterLaneRate_kHz % slowerLaneRate_kHz != 0)
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_SER_LANE_RATE_CONFLICT_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        }
    }
    else
    {
        fasterLaneRate_kHz = (rxLaneRate_kHz >= obsRxLaneRate_kHz) ? (rxLaneRate_kHz) : (obsRxLaneRate_kHz);
    }

    /* performing integer multiple check on HS clock and lane rate clock */
    if (fasterLaneRate_kHz == 0)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_SER_LANERATE_ZERO, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((init->clocks.clkPllVcoFreq_kHz % fasterLaneRate_kHz) != 0)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT, retVal, TALACT_ERR_CHECK_PARAM);
    }

    txser_div = (uint8_t)(init->clocks.clkPllVcoFreq_kHz / fasterLaneRate_kHz);

    switch(txser_div)
    {
        case 1:
            txser_div_reg = 0;
            break;
        case 2:
            txser_div_reg = 1;
            break;
        case 4:
            txser_div_reg = 2;
            break;
        case 8:
            txser_div_reg = 2;
            break;
        default:
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_SER_INV_TXSER_DIV_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Set Tx serializer divider */
    halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_3, txser_div_reg, 0x03, 0);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Power down all lanes */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_JESD_FRAMER_SRST_CFG, 0xFF); /* hold framer output data in reset */
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Reset serializers */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SER_PHY_PD, 0x1E); /* power down all lanes */
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    activeLanesPowerDown = (~((activeLanesEnabled & 0x09) | ((activeLanesEnabled & 0x02) << 1) | ((activeLanesEnabled & 0x04) >> 1)) & 0x0F);
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SER_PHY_PD, (0x80 | (activeLanesPowerDown << 1))); /* power up desired lanes */
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Manual Serializer reset sequence */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SER_PHY_TXCTRL_1, 0x3F);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SER_PHY_TXCTRL_1, 0x2F);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SER_PHY_TXCTRL_1, 0x27);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SER_PHY_TXCTRL_1, 0x23);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SER_PHY_TXCTRL_1, 0x21);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SER_PHY_TXCTRL_1, 0x20);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* data structure encoding: 0 = PreEmp off, 1 = on with preEmp=0 */
    if (preEmp > 0)
    {
        preEmp = preEmp - 1;
    }

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SER_PREEMPH_CTRL, ((preEmp << 4) | (preEmp)));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    enPreEmphasisMask = ((enPreEmphasisMask & 0x09) | ((enPreEmphasisMask & 0x02) << 1) | ((enPreEmphasisMask & 0x04) >> 1));
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SER_PHY_ENABLES, (0x50 | (enPreEmphasisMask & 0x0F)));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SER_PHY_ENABLES, (0x10 | (enPreEmphasisMask & 0x0F)));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Set serializer amplitude */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_SER_PHY_TXCTRL_0, (0x03 | ((serAmplitude & 0x0F) << 3)));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Allow framer data to output to serializer (clear reset) */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_JESD_FRAMER_SRST_CFG, 0x0F);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* correct lane swaps and PN inverts on device laminate - swap lane 1 and 2 and invert all Framer lanes */
    laneInvert = ((laneInvert & 0x09) | ((laneInvert & 0x02) << 1) | ((laneInvert & 0x04) >> 1));
    laneInvert = ~laneInvert;
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_JESD_FRAMER_COMMON_CFG, laneInvert);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Toggle Serializer SRESET */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_JESD_FRAMER_SRST_CFG, 0xFF);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Allow framer data to output to serializer (clear reset) */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_JESD_FRAMER_SRST_CFG, 0x0F);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    return (uint32_t)retVal;
}

uint32_t TALISE_setupDeserializers(taliseDevice_t *device, taliseInit_t *init)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t cdrDiv = 0;
    uint8_t deserializerDiv = 0;
    uint8_t laneInvert = 0;
    uint8_t lanesEnabled = 0;
    uint8_t lanesPowerDown = 0x0F;
    uint8_t halfRateMode = 0;
    uint32_t laneRate_kHz = 0;
    uint8_t totalM = 0;
    uint8_t totalNp = 0;
    uint8_t totalL = 0;
    uint8_t i = 0;
    uint8_t laneRateRatio = 0;
    uint8_t desEqSetting = 0;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_setupDeserializers()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    if (device->devStateInfo.profilesValid & TX_PROFILE_VALID)
    {
        if (init->tx.deframerSel == TAL_DEFRAMER_A)
        {
            lanesEnabled = init->jesd204Settings.deframerA.deserializerLanesEnabled;
            totalM = init->jesd204Settings.deframerA.M;
            totalNp = init->jesd204Settings.deframerA.Np;
        }
        else if (init->tx.deframerSel == TAL_DEFRAMER_B)
        {
            lanesEnabled = init->jesd204Settings.deframerB.deserializerLanesEnabled;
            totalM = init->jesd204Settings.deframerB.M;
            totalNp = init->jesd204Settings.deframerB.Np;
        }
        else if (init->tx.deframerSel == TAL_DEFRAMER_A_AND_B)
        {
            /* verify deframer A and deframer B do not share common physical lanes */
            if ((init->jesd204Settings.deframerA.deserializerLanesEnabled &
                init->jesd204Settings.deframerB.deserializerLanesEnabled) > 0)
            {
                return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                        TAL_ERR_DESER_LANECONFLICT_PARM, retVal, TALACT_ERR_CHECK_PARAM);
            }

            lanesEnabled = init->jesd204Settings.deframerA.deserializerLanesEnabled |
                           init->jesd204Settings.deframerB.deserializerLanesEnabled;

            if (init->jesd204Settings.deframerA.M != init->jesd204Settings.deframerB.M)
            {
                return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                        TAL_ERR_DESER_M_CONFLICT, retVal, TALACT_ERR_CHECK_PARAM);
            }

            if (init->jesd204Settings.deframerA.M > 2)
            {
                return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                        TAL_ERR_DESER_INV_DEFAB_M, retVal, TALACT_ERR_CHECK_PARAM);
            }

            if (init->jesd204Settings.deframerA.Np != init->jesd204Settings.deframerB.Np)
            {
                return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                        TAL_ERR_DESER_NP_CONFLICT, retVal, TALACT_ERR_CHECK_PARAM);
            }

            /* M * 2 since lane rate needs to be calculated with total M for both framers */
            totalM = init->jesd204Settings.deframerA.M * 2;
            totalNp = init->jesd204Settings.deframerA.Np;
        }
        else
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_DESER_INV_DEFRAMERSEL, retVal, TALACT_ERR_CHECK_PARAM);
        }

        if (lanesEnabled > 0x0F)
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_DESER_INV_LANEEN_PARM, retVal, TALACT_ERR_CHECK_PARAM);
        }

        lanesPowerDown = ((~lanesEnabled) & 0x0F);
    }
    else
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DESER_TXPROFILE_INV, retVal, TALACT_ERR_CHECK_PARAM);
    }

    for (i = 0; i < 4; i++)
    {
        totalL += ((lanesEnabled >> i) & 0x01);
    }

    if ((totalL == 0) ||
        (totalL == 3) ||
        (totalL > 4))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DESER_INV_L_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((totalM != 2) &&
        (totalM != 4))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DESER_INV_M_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((totalNp != 12) &&
        (totalNp != 16))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DESER_INV_NP_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    laneRate_kHz = (init->tx.txProfile.txInputRate_kHz * totalM * 10 * totalNp) / (8 * totalL);

    if ((laneRate_kHz < 614400) ||
        (laneRate_kHz > 12288000))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DESER_INV_LANERATE_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (init->clocks.clkPllVcoFreq_kHz % laneRate_kHz != 0)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DESES_HS_AND_LANE_RATE_NOT_INTEGER_MULT, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((totalNp == 12) &&
        (init->clocks.clkPllVcoFreq_kHz != laneRate_kHz))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DESES_INV_LANE_RATE, retVal, TALACT_ERR_CHECK_PARAM);
    }

    laneRateRatio = (uint8_t)(init->clocks.clkPllVcoFreq_kHz / laneRate_kHz);
    switch (laneRateRatio)
    {
        case 1:
            halfRateMode = 1;
            deserializerDiv = 0; /* divide by 1 */
            break;
        case 2:
            halfRateMode = 0; /* Full rate mode */
            deserializerDiv = 0; /* divide by 1 */
            break;
        case 4:
            halfRateMode = 0; /* Full rate mode */
            deserializerDiv = 1; /* divide by 2 */
            break;
        case 8:
            halfRateMode = 0; /* Full rate mode */
            deserializerDiv = 2; /* divide by 2 */
            break;
        case 16:
            halfRateMode = 0; /* Full rate mode */
            deserializerDiv = 3; /* divide by 2 */
            break;
        default:
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_DESES_INV_LANE_RATE_DIV, retVal, TALACT_ERR_CHECK_PARAM);
        }
    }

    if ((init->jesd204Settings.desEqSetting != 0) &&
        (init->jesd204Settings.desEqSetting != 1) &&
        (init->jesd204Settings.desEqSetting != 2))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DESER_INV_EQ_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (init->jesd204Settings.desInvertLanePolarity > 15)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DESER_INV_LANEPN_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Set lane PN inverts - invert all lanes by default due to PN inverts in Talise laminate */
    laneInvert = (~(init->jesd204Settings.desInvertLanePolarity) & 0x0F);

    /* Power up deserializers */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_DES_PHY_PWR_DWN_0, 0x00);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_DES_PHY_PWR_DWN_4, 0x20);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Set deserializer half rate/full rate mode and deserializer divider */
    halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_DES_PHY_CLK_CTL_0, halfRateMode, 0x40, 6);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_DES_PHY_CLK_CTL_1, deserializerDiv);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Set CDR divider - set lane clock frequency (keep lane clock in 3.072G to 6.144G range) */
    cdrDiv = 0;  /* always div 1 on CDR divider */
    halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_CLOCK_CONTROL_3, cdrDiv, 0x0C, 2);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Set lane PN inverts - invert all lanes by default due to PN inverts in Talise laminate */
    halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_JESD_DEFRAMER_COMMON_CFG3, laneInvert, 0xF0, 4);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Set CDR clock enable */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_DES_PHY_GENERAL_CTL_0, 0x90);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Release lane power downs */
    halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_DES_PHY_PWR_DWN_4, lanesPowerDown, 0x0F, 0);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Release deserializer master power down */
    halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_DES_PHY_PWR_DWN_4, 0, 0x20, 5);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Set EQ */
    desEqSetting = (init->jesd204Settings.desEqSetting << 6) | (init->jesd204Settings.desEqSetting << 4) |
                   (init->jesd204Settings.desEqSetting << 2) | init->jesd204Settings.desEqSetting;
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_DES_PHY_EQ_CONTROL2, desEqSetting);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Enable deserializers */
    halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_DES_PHY_GENERAL_CTL_1, 1, 0x10, 4);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    return (uint32_t)retVal;
}

uint32_t TALISE_setupJesd204bFramer(taliseDevice_t *device, taliseInit_t *init, taliseFramerSel_t framerSel)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    taliseJesd204bFramerConfig_t *framer = NULL;
    uint8_t i = 0;
    uint8_t L = 0;
    uint8_t CF = 0;
    uint8_t CS = 0;
    uint8_t S = 1;
    uint8_t JESDVER = 1;
    uint8_t JESDSUBCLASS = 1;
    uint32_t framerAdcXbar = 0;
    uint16_t FK = 0;
    uint8_t HD = 0;
    uint8_t framerLaneXbar = 0xE4;
    uint32_t outputRate_kHz = 0;
    uint8_t pclkDiv = 0;
    uint32_t hsDigClkDiv4or5_Hz = 0;
    uint32_t pclk_Hz = 0;
    uint16_t framerAddrOffset = 0;
    uint8_t scr = 0;

    const uint8_t DUALBANDENABLED = 1;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG,
                            TAL_ERR_OK, "TALISE_setupJesd204bFramer()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
 #endif

    if (framerSel == TAL_FRAMER_A)
    {
        framer = &init->jesd204Settings.framerA;
        framerAddrOffset = 0;
    }
    else if (framerSel == TAL_FRAMER_B)
    {
        framer = &init->jesd204Settings.framerB;
        framerAddrOffset = TALISE_JESD_FRAMERB_OFFSET;
    }
    else
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMER_INV_FRAMERSEL_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (framer->M == 0)
    {
        /* Disable Framer link and exit Framer setup */
        halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG_0 + framerAddrOffset), 0x02);
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    }
    else if ((framer->M == 1) && !(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_INT2_REALIF)
                              && !(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_DEC2_REALIF)
                              && !(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_FILTERONLY_REALIF)
                              && !(init->rx.rxProfile.rxDdcMode == TAL_RXDDC_BYPASS_REALIF))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM, TAL_ERR_SER_INV_ZIF_TO_RIF_DATA_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    else if ((framer->M == 8) &&
            !(device->devStateInfo.rxDualBandEnabled == DUALBANDENABLED))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMER_INV_DUALBAND_DATA_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((framer->M != 1) &&
        (framer->M != 2) &&
        (framer->M != 4) &&
        (framer->M != 8))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMER_INV_M_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((framer->Np != 12) &&
        (framer->Np != 16) &&
        (framer->Np != 24))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMER_INV_NP_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (framer->bankId > 15)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMER_INV_BANKID_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* no need to check deviceId, its range is full uint8_t range */
    if (framer->lane0Id > 31)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMER_INV_LANEID_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (framer->syncbInSelect > 1)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMER_INV_SYNCBIN_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* count number of lanes */
    L = 0;
    for (i = 0; i < 4; i++)
    {
        L += ((framer->serializerLanesEnabled >> i) & 0x01);
    }

    if (L == 0)
    {
        /* Disable Link, and return from function */
        halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG_0 + framerAddrOffset), 0x02);
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    }
    else if ((L != 1) &&
             (L != 2) &&
             (L != 4))
    {
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_RXFRAMER_INV_L_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Check for fractional S value  - invalid settings */
    if (((framer->F * L * 8) % (framer->Np * framer->M)) > 0)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMER_INV_S_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    S = (framer->F * L * 8) / (framer->Np * framer->M);
    if ((S != 1) &&
        (S != 2) &&
        (S != 4) &&
        (S != 8))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMER_INV_S_PARM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    FK = ((uint16_t)(framer->K) * (uint16_t)(framer->F));

    if ((FK < 20) ||
        (FK > 1024) ||
        (FK % 4 != 0))
    {
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_RXFRAMER_INV_FK_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    HD = ((((uint16_t)(framer->F) * 8) % framer->Np) > 0) ? (1) : (0);

    if (framer->enableManualLaneXbar != 0) {
        framerLaneXbar = framer->serializerLaneCrossbar;
    }
    else
    {
        switch((framer->serializerLanesEnabled & 0x0F))
        {
            /* Lanes 1 and 2 are swapped on laminate, correct here */
            /* Set unused lanes to select value b11 */
            case 1:  framerLaneXbar = 0xFC; break;
            case 2:  framerLaneXbar = 0xCF; break;
            case 3:  framerLaneXbar = 0xDC; break;
            case 4:  framerLaneXbar = 0xF3; break;
            case 5:  framerLaneXbar = 0xF4; break;
            case 6:  framerLaneXbar = 0xC7; break;
            case 8:  framerLaneXbar = 0x3F; break;
            case 9:  framerLaneXbar = 0x7C; break;
            case 10: framerLaneXbar = 0x4F; break;
            case 12: framerLaneXbar = 0x73; break;
            case 15: framerLaneXbar = 0xD8; break;
            default: framerLaneXbar = 0xD8; break;
        }
    }

    if (framer->M == 8)
    {
        framerAdcXbar = 0x37251301;
    }
    else
    {
        framerAdcXbar = 0x00001301;
    }

    /* Determine framer PCLK frequency */
    if (device->devStateInfo.profilesValid & RX_PROFILE_VALID)
    {
        /* If Rx profile is using this framer, use the Rx IQ data rate */
        if ((init->rx.framerSel == TAL_FRAMER_A_AND_B) ||
            (init->rx.framerSel == framerSel))
        {
            outputRate_kHz = init->rx.rxProfile.rxOutputRate_kHz;
        }
    }

    if (device->devStateInfo.profilesValid & ORX_PROFILE_VALID)
    {
        /* If ORx profile is using this framer, use the ORx IQ data rate */
        if ((init->obsRx.framerSel == TAL_FRAMER_A_AND_B) || (init->obsRx.framerSel == framerSel))
        {
            outputRate_kHz = init->obsRx.orxProfile.orxOutputRate_kHz;
        }
    }

    /* If Rx and ORx share same framer - set PCLK to faster of two rates */
    if ((device->devStateInfo.profilesValid & RX_PROFILE_VALID) &&
        (device->devStateInfo.profilesValid & ORX_PROFILE_VALID) &&
        (init->rx.framerSel == init->obsRx.framerSel) &&
        (init->rx.framerSel == framerSel))
    {
        if (init->obsRx.orxProfile.orxOutputRate_kHz > init->rx.rxProfile.rxOutputRate_kHz)
        {
            outputRate_kHz =  init->obsRx.orxProfile.orxOutputRate_kHz;
        }
        else
        {
            outputRate_kHz = init->rx.rxProfile.rxOutputRate_kHz;
        }
    }

    if (outputRate_kHz == 0)
    {
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_RXFRAMER_INV_OUTPUT_RATE, retVal, TALACT_ERR_CHECK_PARAM);
    }

    pclk_Hz = (outputRate_kHz * (uint32_t)(framer->F) * 1000) / ((uint32_t)(S) * 4);

    /* Determine PCLK divider */

    hsDigClkDiv4or5_Hz = device->devStateInfo.clocks.hsDigClkDiv4or5_Hz;

    if ((framer->F == 3) ||
        (framer->F == 6))
    {
        pclkDiv = 0;
    }
    else
    {
        for (pclkDiv = 0; pclkDiv < 8; pclkDiv++)
        {
            if ((hsDigClkDiv4or5_Hz >> pclkDiv) == pclk_Hz)
            {
                break; /* Use current pclk divider */
            }

            if (pclkDiv == 7)
            {
                return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                        TAL_ERR_RXFRAMER_INV_PCLKFREQ, retVal, TALACT_ERR_CHECK_PARAM);
            }
        }
    }

    /* Disable JESD204b link enable */
    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG_0 + framerAddrOffset), ((framer->syncbInSelect << 5) | 0x02));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_L0_CFG0_0 + framerAddrOffset), framer->deviceId); /* DID */
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_L0_CFG1_0 + framerAddrOffset), (framer->bankId & 0x0F));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_L0_CFG2_0 + framerAddrOffset), (framer->lane0Id & 0x1F));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    scr = (framer->scramble == 0) ? 0x00 : 0x80;

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_L0_CFG3_0 + framerAddrOffset), (scr | ((L-1) & 0x1F)));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_L0_CFG4_0 + framerAddrOffset), (framer->F - 1));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_L0_CFG5_0 + framerAddrOffset), (framer->K - 1));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_L0_CFG6_0 + framerAddrOffset), (framer->M - 1));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_L0_CFG7_0 + framerAddrOffset), (((CS & 3) << 6) | ((framer->Np & 0x1F) - 1)));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_L0_CFG8_0 + framerAddrOffset), (((JESDSUBCLASS & 7) << 5) | ((framer->Np & 0x1F) - 1)));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_L0_CFG9_0 + framerAddrOffset), (((JESDVER & 7) << 5) | (S - 1)));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_L0_CFG10_0 + framerAddrOffset), ((HD << 7) | (CF & 0x1F)));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_JESD_FRAMER_ILAS_MF_COUNT_0, 0x00); /* 4 multiframes in ILAS */
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Sample Crossbar */
    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_SAMPLE_XBAR_01_0 + framerAddrOffset), (uint8_t)(framerAdcXbar));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_SAMPLE_XBAR_23_0 + framerAddrOffset), (uint8_t)(framerAdcXbar >> 8));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_SAMPLE_XBAR_45_0 + framerAddrOffset), (uint8_t)(framerAdcXbar >> 16));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_SAMPLE_XBAR_67_0 + framerAddrOffset), (uint8_t)(framerAdcXbar >> 24));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Framer: Set Lane Crossbar */
    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_LANE_XBAR_0 + framerAddrOffset), framerLaneXbar);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* enabling the SYSREF for relink if newSysrefOnRelink is set */
    if (framer->newSysrefOnRelink > 0)
    {
        halError = talSpiWriteField(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_SYSREF_CFG_0 + framerAddrOffset), 0x01, 0x02, 1);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    if (framer->lmfcOffset < framer->K)
    {
        halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG5_0 + framerAddrOffset), ((pclkDiv << 5) | (framer->lmfcOffset & 0x1F)));
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }
    else
    {
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMER_INV_LMFC_OFFSET_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* If 11G mode, set async PCLK bit */
    if ((framer->F == 3) ||
        (framer->F == 6))
    {
        halError = talSpiWriteField(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG4_0 + framerAddrOffset), 0x01, 0x08, 3);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    /* Enable Framer link */
    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG_0 + framerAddrOffset), ((framer->syncbInSelect << 5) | 0x03));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    return (uint32_t)retVal;
}

uint32_t TALISE_setupJesd204bDeframer(taliseDevice_t *device, taliseInit_t *init, taliseDeframerSel_t deframerSel)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint16_t deframerAddrOffset = 0;
    taliseJesd204bDeframerConfig_t *deframer = NULL;
    uint8_t i = 0;
    uint8_t newSysrefOnRelink = 0;
    uint8_t scr = 0;
    uint8_t L = 0;
    uint8_t F = 0;
    uint8_t S = 1;
    uint32_t pclk_kHz = 0;
    uint16_t FK = 0;
    uint8_t HD = 0;
    uint32_t hsDigClkDiv4or5_Hz = 0;
    uint8_t pclkDiv = 0;
    uint8_t pclkReg = 0;
    uint8_t extSysref = 0;
    uint8_t syncBarSel = 1;
    uint8_t deframerInput = 0;
    uint8_t lane = 0;
    uint8_t deframerlaneXbar = 0;

    static const uint8_t CS = 0;
    static const uint8_t CF = 0;
    static const uint8_t SUBCLASSV = 1;
    static const uint8_t JESDV = 1;
    static const uint8_t DFRMRCMMIRQMASK = 0x80;

    if (device->devStateInfo.profilesValid & TX_PROFILE_VALID)
    {
        if (deframerSel == TAL_DEFRAMER_A)
        {
            deframerAddrOffset = 0;
            deframer = &init->jesd204Settings.deframerA;
        }
        else if (deframerSel == TAL_DEFRAMER_B)
        {
            deframerAddrOffset = TALISE_JESD_DEFRAMERB_OFFSET;
            deframer = &init->jesd204Settings.deframerB;
        }
        else
        {
            return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_DEFRAMER_INV_DEFSEL, retVal, TALACT_ERR_CHECK_PARAM);
        }
    }
    else
    {
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DEFRAMER_INV_TXPROFILE, retVal, TALACT_ERR_CHECK_PARAM);
    }

    newSysrefOnRelink = (deframer->newSysrefOnRelink > 0) ? 1 : 0;

    scr = (deframer->scramble > 0) ? 1 : 0;

    if (deframer->deserializerLanesEnabled > 15)
    {
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DEFRAMER_INV_LANESEN, retVal, TALACT_ERR_CHECK_PARAM);
    }

    for (i = 0; i < 4; i++)
    {
        L += ((deframer->deserializerLanesEnabled >> i) & 0x01);
    }

    if ((L != 1) &&
        (L != 2) &&
        (L != 4))
    {
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DEFRAMER_INV_L, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((deframer->M != 2) &&
        (deframer->M != 4))
    {
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DEFRAMER_INV_M, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((deframer->Np != 12) &&
        (deframer->Np != 16))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DEFRAMER_INV_NP, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Check for fractional F - invalid settings */
    if(device->devStateInfo.swTest > 0)
    {
        /*For a software test bypass bounds checking on F and assign a valid value*/
        F = 2;
    }
    else
    {
        if (((deframer->Np * deframer->M * S) % (8 * L)) > 0)
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_DEFRAMER_INV_F, retVal, TALACT_ERR_CHECK_PARAM);
        }

        F = (deframer->Np * deframer->M * S) / (8 * L);
    }

    if ((F < 1) ||
        (F > 32))
    {
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DEFRAMER_INV_F, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((deframer->K < 1) ||
        (deframer->K > 32))
    {
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DEFRAMER_INV_K, retVal, TALACT_ERR_CHECK_PARAM);
    }

    FK = (uint16_t)F * (uint16_t)deframer->K;
    if (((FK % 4) != 0) ||
         (FK < 20) ||
         (FK > 1024))
    {
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DEFRAMER_INV_FK, retVal, TALACT_ERR_CHECK_PARAM);
    }

    pclk_kHz = init->tx.txProfile.txInputRate_kHz * (uint32_t)(F) / (uint32_t)(S) / 4;
    HD = ((((uint16_t)(F) * 8) % deframer->Np) > 0) ? 1 : 0;

    hsDigClkDiv4or5_Hz = device->devStateInfo.clocks.hsDigClkDiv4or5_Hz;

    if ((F == 3) ||
        (F == 6))
    {
        pclkReg = 0;
    }
    else
    {
        if (((hsDigClkDiv4or5_Hz / 1000) % pclk_kHz) != 0)
        {
            return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_DEFRAMER_INV_PCLK, retVal, TALACT_ERR_CHECK_PARAM);
        }

        pclkDiv = (uint8_t)(hsDigClkDiv4or5_Hz / 1000 / pclk_kHz);

        switch (pclkDiv)
        {
            case 1:
                pclkReg = 0; /* PCLK = HsDigClk /4 */
                break;
            case 2:
                pclkReg = 1; /* PCLK = HsDigClk /8 */
                break;
            case 4:
                pclkReg = 2; /* PCLK = HsDigClk /16 */
                break;
            case 8:
                pclkReg = 3; /* PCLK = HsDigClk /32 */
                break;
            case 16:
                pclkReg = 4; /* PCLK = HsDigClk /64 */
                break;
            case 32:
                pclkReg = 5; /* PCLK = HsDigClk /128 */
                break;
            default:
            {
                return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                        TAL_ERR_DEFRAMER_INV_PCLKDIV, retVal, TALACT_ERR_CHECK_PARAM);
            }
        }
    }

    if (deframer->bankId > 15)
    {
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DEFRAMER_INV_BANKID, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (deframer->lane0Id > 31)
    {
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_ERR_DEFRAMER_INV_LANEID, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (deframer->lmfcOffset >= deframer->K)
    {
        return (uint32_t)talApiErrHandler(device,TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DEFRAMER_INV_LMFC_OFFSET, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Disable deframer link */
    retVal = (talRecoveryActions_t)TALISE_enableDeframerLink(device, deframerSel, 0);
    IF_ERR_RETURN_U32(retVal);

    /* checksum mode - clear [7] for correct mode */
    halError = talSpiWriteField(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_CFG3_0 + deframerAddrOffset), 0, 0x80, 7);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Disable Deframer CMM IRQ Interrupt */
    halError = talSpiWriteField(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_IP_CFG3_0 + deframerAddrOffset), DFRMRCMMIRQMASK, 0x80, 0);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Set LMFC Offset */
    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_CFG4_0 + deframerAddrOffset), deframer->lmfcOffset);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    extSysref = (deframer->externalSysref > 0) ? 1 : 0;
    halError = talSpiWriteField(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_SYSREF_CFG2_0 + deframerAddrOffset), extSysref, 0x20, 5);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* If no external sysref, also clear SYSREF enable bit */
    if (extSysref == 0)
    {
        halError = talSpiWriteField(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_SYSREF_CFG_0 + deframerAddrOffset), 0, 0x01, 0);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    halError = talSpiWriteField(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_SYSREF_CFG_0 + deframerAddrOffset), newSysrefOnRelink, 0x02, 1);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* set PCLK for deframers */
    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_JESD_DEFRAMER_COMMON_CFG, (0x10 | pclkReg));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* select SYNCOUTB 0 or 1 pin */
    /* TODO: Fix this SYNCB selection - can use both and they get ANDed*/

    syncBarSel = (deframer->syncbOutSelect > 0) ? 2 : 1;

    halError = talSpiWriteField(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_CFG_0 + deframerAddrOffset), syncBarSel, 0x60, 5);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_L0_CFG0_0 + deframerAddrOffset), deframer->deviceId);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_L0_CFG1_0 + deframerAddrOffset), (deframer->bankId & 0x0F));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_L0_CFG2_0 + deframerAddrOffset), (deframer->lane0Id & 0x1F));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_L0_CFG3_0 + deframerAddrOffset), ((scr << 7) | ((L - 1) & 0x1F)));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_L0_CFG4_0 + deframerAddrOffset), (F - 1));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_L0_CFG5_0 + deframerAddrOffset), ((deframer->K - 1) & 0x1F));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_L0_CFG6_0 + deframerAddrOffset), (deframer->M - 1));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_L0_CFG7_0 + deframerAddrOffset), (((CS & 0x03) << 6) | ((deframer->Np - 1) & 0x1F)));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_L0_CFG8_0 + deframerAddrOffset), (((SUBCLASSV & 0x7) << 5) | ((deframer->Np - 1) & 0x1F)));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_L0_CFG9_0 + deframerAddrOffset), (((JESDV & 0x7) << 5) | ((S - 1) & 0x1F)));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_L0_CFG10_0 + deframerAddrOffset), ((HD << 7) | (CF * 0x1F)));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_ILAS_MF_COUNT_0 + deframerAddrOffset), 0x00);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    if (deframer->enableManualLaneXbar != 0) {
        deframerlaneXbar = deframer->deserializerLaneCrossbar;
    }
    else
    {
        /* Lane crossbar  - Allow user to reorder lanes in deframer->deserializerLaneCrossbar, but this code still */
        /* maps used lanes to deframer inputs */
        deframerInput = 0;
        for (lane = 0; lane < 4; lane++)
        {
            if ((deframer->deserializerLanesEnabled >> lane) & 1)
            {
                deframerlaneXbar |= (((deframer->deserializerLaneCrossbar >> (lane << 1)) & 3) << (deframerInput << 1));
                deframerInput += 1;
            }
        }
    }
    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_LANE_XBAR_0 + deframerAddrOffset), deframerlaneXbar);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Enable deframer link */
    retVal = (talRecoveryActions_t)TALISE_enableDeframerLink(device, deframerSel, 1);
    IF_ERR_RETURN_U32(retVal);

    return (uint32_t)retVal;
}

uint32_t TALISE_enableFramerLink(taliseDevice_t *device, taliseFramerSel_t framerSel, uint8_t enable)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t enableLink = 0;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_enableFramerLink()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    enableLink = (enable > 0) ? 1 : 0;

    if ((framerSel != TAL_FRAMER_A) && (framerSel != TAL_FRAMER_B) && (framerSel != TAL_FRAMER_A_AND_B))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_RSTFRAMER_INV_FRAMERSEL, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((framerSel == TAL_FRAMER_A) ||
        (framerSel == TAL_FRAMER_A_AND_B))
    {
        halError = talSpiWriteField(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG_0), enableLink, 0x01, 0);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);

    }

    if ((framerSel == TAL_FRAMER_B) ||
        (framerSel == TAL_FRAMER_A_AND_B))
    {
        halError = talSpiWriteField(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG_0 + TALISE_JESD_FRAMERB_OFFSET), enableLink, 0x01, 0);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    return (uint32_t)retVal;
}

uint32_t TALISE_enableDeframerLink(taliseDevice_t *device, taliseDeframerSel_t deframerSel, uint8_t enable)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint16_t deframerOffset = 0;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_enableDeframerLink()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    if (deframerSel == TAL_DEFRAMER_A)
    {
        deframerOffset = 0;
    }
    else if (deframerSel == TAL_DEFRAMER_B)
    {
        deframerOffset = TALISE_JESD_DEFRAMERB_OFFSET;
    }
    else
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_RSTDEFRAMER_INV_DEFSEL, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (enable > 0)
    {
        /* Enable the deframer JESD link */
        halError = talSpiWriteField(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_CFG_0 + deframerOffset), 1, 0x01, 0);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }
    else
    {
        /* clear deframer link enable bit */
        halError = talSpiWriteField(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_CFG_0 + deframerOffset), 0, 0x01, 0);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    return (uint32_t)retVal;
}

uint32_t TALISE_enableSysrefToFramer(taliseDevice_t *device, taliseFramerSel_t framerSel, uint8_t enable)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t enableSysref = 0;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_enableSysrefToFramer()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    enableSysref = (enable > 0) ? 1 : 0;

    if ((framerSel != TAL_FRAMER_A) &&
        (framerSel != TAL_FRAMER_B) &&
        (framerSel != TAL_FRAMER_A_AND_B))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_ENFRAMERSYSREF_INV_FRAMERSEL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((framerSel == TAL_FRAMER_A) ||
        (framerSel == TAL_FRAMER_A_AND_B))
    {
        halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_JESD_FRAMER_SYSREF_CFG_0, enableSysref, 0x01, 0);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    if ((framerSel == TAL_FRAMER_B) ||
        (framerSel == TAL_FRAMER_A_AND_B))
    {
        halError = talSpiWriteField(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_SYSREF_CFG_0 + TALISE_JESD_FRAMERB_OFFSET), enableSysref, 0x01, 0);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    return (uint32_t)retVal;
}

uint32_t TALISE_enableSysrefToDeframer(taliseDevice_t *device, taliseDeframerSel_t deframerSel, uint8_t enable)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t enableSysref = 0;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_enableSysrefToDeframer()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    enableSysref = (enable > 0) ? 1 : 0;

    if ((deframerSel != TAL_DEFRAMER_A) &&
        (deframerSel != TAL_DEFRAMER_B) &&
        (deframerSel != TAL_DEFRAMER_A_AND_B))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_ENDEFSYSREF_INV_DEFRAMERSEL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((deframerSel == TAL_DEFRAMER_A) ||
        (deframerSel == TAL_DEFRAMER_A_AND_B))
    {
        halError = talSpiWriteField(device->devHalInfo, TALISE_ADDR_JESD_DEFRAMER_SYSREF_CFG_0, enableSysref, 0x01, 0);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    if ((deframerSel == TAL_DEFRAMER_B) ||
        (deframerSel == TAL_DEFRAMER_A_AND_B))
    {
        halError = talSpiWriteField(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_SYSREF_CFG_0 + TALISE_JESD_DEFRAMERB_OFFSET), enableSysref, 0x01, 0);
        retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    return (uint32_t)retVal;
}

uint32_t TALISE_readFramerStatus(taliseDevice_t *device, taliseFramerSel_t framerSel, uint8_t *framerStatus)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t sysrefStatus = 0;
    uint8_t configStatus3 = 0;
    uint8_t configStatus4 = 0;
    uint8_t syncStatus = 0;
    uint16_t sysrefStatusAddr = TALISE_ADDR_JESD_FRAMER_SYSREF_CFG2_0;
    uint16_t syncStatusAddr = TALISE_ADDR_JESD_FRAMER_CFG_0;
    uint16_t configStatus3Addr = TALISE_ADDR_JESD_FRAMER_SYSREF_CFG3_0;
    uint16_t configStatus4Addr = TALISE_ADDR_JESD_FRAMER_CFG4_0;
    static const uint8_t INVALIDCFG_STS_MIN_SUPPORTED_SIREV = 0xC0;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_readFramerStatus()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    if (framerSel == TAL_FRAMER_A)
    {
        sysrefStatusAddr = TALISE_ADDR_JESD_FRAMER_SYSREF_CFG2_0;
        syncStatusAddr = TALISE_ADDR_JESD_FRAMER_CFG_0;
        configStatus3Addr = TALISE_ADDR_JESD_FRAMER_CFG3_0;
        configStatus4Addr = TALISE_ADDR_JESD_FRAMER_CFG4_0;
    }
    else if (framerSel == TAL_FRAMER_B)
    {
        sysrefStatusAddr = TALISE_ADDR_JESD_FRAMER_SYSREF_CFG2_0 + TALISE_JESD_FRAMERB_OFFSET;
        syncStatusAddr = TALISE_ADDR_JESD_FRAMER_CFG_0 + TALISE_JESD_FRAMERB_OFFSET;
        configStatus3Addr = TALISE_ADDR_JESD_FRAMER_CFG3_0 + TALISE_JESD_FRAMERB_OFFSET;
        configStatus4Addr = TALISE_ADDR_JESD_FRAMER_CFG4_0 + TALISE_JESD_FRAMERB_OFFSET;
    }
    else
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                 TAL_ERR_FRAMERSTATUS_INV_FRAMERSEL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (framerStatus == NULL)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMERSTATUS_NULL_FRAMERSTATUS_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    halError = ADIHAL_spiReadField(device->devHalInfo, sysrefStatusAddr, &sysrefStatus, 0x03, 0);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = ADIHAL_spiReadField(device->devHalInfo, syncStatusAddr, &syncStatus, 0x30, 4);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = ADIHAL_spiReadField(device->devHalInfo, configStatus3Addr, &configStatus3, 0x01, 0);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /*Read Invalid Framer Config status only if Silicon Revision is C0 or higher, else report 0 as invalid config*/
    if(device->devStateInfo.deviceSiRev >= INVALIDCFG_STS_MIN_SUPPORTED_SIREV)
    {
        halError = ADIHAL_spiReadField(device->devHalInfo, configStatus4Addr, &configStatus4, 0x01, 0);
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    *framerStatus = (configStatus4 << 6) | (configStatus3 << 5) | (syncStatus << 2) | sysrefStatus;

    return (uint32_t)retVal;
}

uint32_t TALISE_readDeframerStatus(taliseDevice_t *device, taliseDeframerSel_t deframerSel, uint16_t *deframerStatus)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint16_t deframerOffset = 0;
    uint16_t configStatus3Addr = TALISE_ADDR_JESD_DEFRAMER_CFG3_0;
    uint8_t configStatus3 = 0;
    uint8_t eventObs = 0;
    static const uint8_t INVALIDCFG_STS_MIN_SUPPORTED_SIREV = 0xC0;

#if TALISE_VERBOSE
    talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_readDeframerStatus()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    if (deframerSel == TAL_DEFRAMER_A)
    {
        deframerOffset = 0;
    }
    else if (deframerSel == TAL_DEFRAMER_B)
    {
        deframerOffset = TALISE_JESD_DEFRAMERB_OFFSET;
    }
    else
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DEFSTATUS_INV_DEFRAMERSEL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (deframerStatus == NULL)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_DEFSTATUS_NULL_DEFRAMERSTATUS_PARAM, retVal, TALACT_ERR_CHECK_PARAM);

    }

    halError = talSpiReadByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_EVENT_OBS_0 + deframerOffset), &eventObs);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    if(device->devStateInfo.deviceSiRev >= INVALIDCFG_STS_MIN_SUPPORTED_SIREV)
    {
        halError = ADIHAL_spiReadField(device->devHalInfo, (configStatus3Addr + deframerOffset), &configStatus3, 0x01, 0);
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    *deframerStatus = ((configStatus3 << 8) | eventObs);

    return (uint32_t)retVal;
}

static talRecoveryActions_t talCheckDacSampleXbarSelectEnum (taliseDevice_t *device, taliseDacSampleXbarSelect_t lane)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    if ((lane != TAL_DEFRAMERA_OUT0) && (lane != TAL_DEFRAMERA_OUT1) &&
        (lane != TAL_DEFRAMERA_OUT2) && (lane != TAL_DEFRAMERA_OUT3) &&
        (lane != TAL_DEFRAMERB_OUT0) && (lane != TAL_DEFRAMERB_OUT1) &&
        (lane != TAL_DEFRAMERB_OUT2) && (lane != TAL_DEFRAMERB_OUT3))
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_INV_DAC_SAMP_XBAR_SELECT_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }
    return retVal;
}

uint32_t TALISE_setupDacSampleXbar(taliseDevice_t *device, taliseTxChannels_t channelSel, taliseDacSampleXbar_t dacXbar)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint16_t channelAddr = 0;
    uint8_t xbarReg = 0;
    static const uint8_t CONV_MASK = 0x07;
    static const uint8_t CONV_POS  = 0x4;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_setupDacSampleXbar()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    /* performing Tx channel selection check */
    switch (channelSel)
    {
        case TAL_TX1:
            channelAddr = TALISE_ADDR_JESD_DEFRAMER_CH1_SAMPLE_XBAR;
            break;
        case TAL_TX2:
            channelAddr = TALISE_ADDR_JESD_DEFRAMER_CH2_SAMPLE_XBAR;
            break;
        default:
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_INV_DAC_SAMP_XBAR_CHANNEL_SEL, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Check Crossbar for valid settings */
    retVal = talCheckDacSampleXbarSelectEnum (device, dacXbar.dacChanI);
    IF_ERR_RETURN_U32(retVal);
    retVal = talCheckDacSampleXbarSelectEnum (device, dacXbar.dacChanQ);
    IF_ERR_RETURN_U32(retVal);

    /* setting the DAC sample crossbar */
    xbarReg = (((uint8_t)dacXbar.dacChanI) & CONV_MASK) | ((((uint8_t)dacXbar.dacChanQ) & CONV_MASK) << CONV_POS);
    halError = talSpiWriteByte(device->devHalInfo, channelAddr, xbarReg);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    return (uint32_t)retVal;
}

static talRecoveryActions_t talCheckAdcSampleXbarSelectEnum (taliseDevice_t *device, taliseAdcSampleXbarSelect_t conv)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    if ((conv != TAL_ADC_RX1_I) &&
        (conv != TAL_ADC_RX1_Q) &&
        (conv != TAL_ADC_RX2_I) &&
        (conv != TAL_ADC_RX2_Q) &&
        (conv != TAL_ADC_DUALBAND_RX1_BAND_A_I) &&
        (conv != TAL_ADC_DUALBAND_RX1_BAND_A_Q) &&
        (conv != TAL_ADC_DUALBAND_RX2_BAND_A_I) &&
        (conv != TAL_ADC_DUALBAND_RX2_BAND_A_Q) &&
        (conv != TAL_ADC_DUALBAND_RX1_BAND_B_I) &&
        (conv != TAL_ADC_DUALBAND_RX1_BAND_B_Q) &&
        (conv != TAL_ADC_DUALBAND_RX2_BAND_B_I) &&
        (conv != TAL_ADC_DUALBAND_RX2_BAND_B_Q))
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_INV_ADC_SAMP_XBAR_SELECT_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }
    return retVal;
}

uint32_t TALISE_setupAdcSampleXbar(taliseDevice_t *device, taliseFramerSel_t framerSel, taliseAdcSampleXbar_t adcXbar)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint16_t framerOffset = 0;
    uint8_t xbarReg = 0;
    static const uint8_t CONV_MASK = 0x07;
    static const uint8_t CONV_POS  = 0x3;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_setupAdcSampleXbar()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    switch (framerSel)
    {
        case TAL_FRAMER_A:
            framerOffset = 0;
            break;
        case TAL_FRAMER_B:
            framerOffset = TALISE_JESD_FRAMERB_OFFSET;
            break;
        default:
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                    TAL_ERR_INV_ADC_SAMP_XBAR_FRAMER_SEL, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Check Crossbar for valid settings */
    retVal = talCheckAdcSampleXbarSelectEnum (device, adcXbar.conv0);
    IF_ERR_RETURN_U32(retVal);
    retVal = talCheckAdcSampleXbarSelectEnum (device, adcXbar.conv1);
    IF_ERR_RETURN_U32(retVal);
    retVal = talCheckAdcSampleXbarSelectEnum (device, adcXbar.conv2);
    IF_ERR_RETURN_U32(retVal);
    retVal = talCheckAdcSampleXbarSelectEnum (device, adcXbar.conv3);
    IF_ERR_RETURN_U32(retVal);
    retVal = talCheckAdcSampleXbarSelectEnum (device, adcXbar.conv4);
    IF_ERR_RETURN_U32(retVal);
    retVal = talCheckAdcSampleXbarSelectEnum (device, adcXbar.conv5);
    IF_ERR_RETURN_U32(retVal);
    retVal = talCheckAdcSampleXbarSelectEnum (device, adcXbar.conv6);
    IF_ERR_RETURN_U32(retVal);
    retVal = talCheckAdcSampleXbarSelectEnum (device, adcXbar.conv7);
    IF_ERR_RETURN_U32(retVal);

    /* writing setting to the ADC sample crossbar */
    xbarReg = (((uint8_t)adcXbar.conv0) & CONV_MASK) | ((((uint8_t)adcXbar.conv1) & CONV_MASK) << CONV_POS);
    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_SAMPLE_XBAR_01_0 + framerOffset), xbarReg);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    xbarReg = (((uint8_t)adcXbar.conv2) & CONV_MASK) | ((((uint8_t)adcXbar.conv3) & CONV_MASK) << CONV_POS);
    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_SAMPLE_XBAR_23_0 + framerOffset), xbarReg);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    xbarReg = (((uint8_t)adcXbar.conv4) & CONV_MASK) | ((((uint8_t)adcXbar.conv5) & CONV_MASK) << CONV_POS);
    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_SAMPLE_XBAR_45_0 + framerOffset), xbarReg);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    xbarReg = (((uint8_t)adcXbar.conv6) & CONV_MASK) | ((((uint8_t)adcXbar.conv7) & CONV_MASK) << CONV_POS);
    halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_SAMPLE_XBAR_67_0 + framerOffset), xbarReg);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    return (uint32_t)retVal;
}

uint32_t TALISE_enableFramerTestData(taliseDevice_t *device, taliseFramerSel_t framerSelect, taliseFramerDataSource_t testDataSource, taliseFramerInjectPoint_t injectPoint)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_enableFramerTestData()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    if (testDataSource > TAL_FTD_RAMP)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMER_INV_TESTDATA_SOURCE_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (injectPoint > TAL_FTD_POST_LANEMAP)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMER_INV_INJECTPOINT_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((framerSelect != TAL_FRAMER_A) &&
        (framerSelect != TAL_FRAMER_B) &&
        (framerSelect != TAL_FRAMER_A_AND_B))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMER_INV_FRAMERSEL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if ((framerSelect == TAL_FRAMER_A) ||
        (framerSelect == TAL_FRAMER_A_AND_B))
    {
        halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_JESD_FRAMER_TEST_CFG_0, (uint8_t)((injectPoint << 4) | (testDataSource)));
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    if ((framerSelect == TAL_FRAMER_B) ||
        (framerSelect == TAL_FRAMER_A_AND_B))
    {
        halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_TEST_CFG_0 + TALISE_JESD_FRAMERB_OFFSET), (uint8_t)((injectPoint << 4) | (testDataSource)));
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    return (uint32_t)retVal;
}

uint32_t TALISE_injectFramerTestDataError(taliseDevice_t *device, taliseFramerSel_t framerSelect)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint16_t testDataInvertAddr = TALISE_ADDR_JESD_FRAMER_TEST_CFG_0;
    uint8_t readData = 0;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_injectFramerTestDataError()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    if (framerSelect == TAL_FRAMER_A)
    {
        testDataInvertAddr = TALISE_ADDR_JESD_FRAMER_TEST_CFG_0;
    }
    else if (framerSelect == TAL_FRAMER_B)
    {
        testDataInvertAddr = (TALISE_ADDR_JESD_FRAMER_TEST_CFG_0 + TALISE_JESD_FRAMERB_OFFSET);
    }
    else
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMER_ERRINJECT_INV_FRAMERSEL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* reading current PRBS control register contents */
    halError = talSpiReadByte(device->devHalInfo, testDataInvertAddr, &readData);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* invert test data, then invert back to normal */
    halError = talSpiWriteByte(device->devHalInfo, testDataInvertAddr, (readData |= 0x40));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteByte(device->devHalInfo, testDataInvertAddr, (readData &= ~0x40));
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    return (uint32_t)retVal;
}

uint32_t TALISE_enableDeframerPrbsChecker(taliseDevice_t *device, taliseDeframerPrbsOrder_t polyOrder, taliseDefPrbsCheckLoc_t checkerLocation)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    talRecoveryActions_t retValWarn = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;


#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_enableDeframerPrbsChecker()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    retValWarn = retVal;

    if ((polyOrder >= TAL_PRBS_DISABLE) &&
        (polyOrder <= TAL_PRBS31) &&
        (checkerLocation >= TAL_PRBSCHECK_LANEDATA) &&
        (checkerLocation <= TAL_PRBSCHECK_SAMPLEDATA))
    {

        retVal = (talRecoveryActions_t)TALISE_clearDeframerPrbsCounters(device);
        IF_ERR_RETURN_U32(retVal);

        halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_JESD_DEFRAMER_PRBS_CFG, (uint8_t)((polyOrder << 2) | checkerLocation));
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }
    else
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                   TAL_ERR_EN_DEFRAMER_PRBS_INV_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* If higher priority retVal has no error, allow possible lower priority warning to be returned */
    if (retVal == TALACT_NO_ACTION)
    {
        retVal = retValWarn;
    }

    return (uint32_t)retVal;
}

uint32_t TALISE_clearDeframerPrbsCounters(taliseDevice_t *device)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_clearDeframerPrbsCounters()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_JESD_DEFRAMER_PRBS_ERROR_FLAG, 0x00);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    return (uint32_t)retVal;
}

uint32_t TALISE_readDeframerPrbsCounters(taliseDevice_t *device, uint8_t lane, uint8_t *prbsErrorCount, uint8_t *prbsInvertedStatus)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t prbsCheckLocation = 0;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_readDeframerPrbsCounters()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    if (prbsErrorCount == NULL)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
            TAL_ERR_READDFRMPRBS_NULL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (prbsInvertedStatus == NULL)
     {
         return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
             TAL_ERR_READDFRMPRBS_NULL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
     }

    /* Read back deframer output 0 sample counter */
     halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_JESD_DEFRAMER_PRBS_CFG, &prbsCheckLocation);
     retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
     IF_ERR_RETURN_U32(retVal);

    /* Save Lane Data Inverted Status */
    *prbsInvertedStatus =  ((prbsCheckLocation & 0xF0) >> 4);

    /* Mask off the source bit */
    prbsCheckLocation = (prbsCheckLocation & 0x01);

    if (((taliseDefPrbsCheckLoc_t) prbsCheckLocation) == TAL_PRBSCHECK_SAMPLEDATA)
    {
        /* Write to update deframer output 0 sample counter */
        halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_JESD_DEFRAMER_SAMPLE_PRBS_ERROR_COUNT, 0);
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);

        /* Read back deframer output 0 sample counter */
        halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_JESD_DEFRAMER_SAMPLE_PRBS_ERROR_COUNT, prbsErrorCount);
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }
    else
    {
        /* Write PRBS error Count register to force prbs error count update for all 4 lanes */
        halError = talSpiWriteByte(device->devHalInfo, TALISE_ADDR_JESD_DEFRAMER_PRBS_ERROR_COUNT0, 0);
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);

        if (lane == 0)
        {
            halError = talSpiReadByte(device->devHalInfo, TALISE_ADDR_JESD_DEFRAMER_PRBS_ERROR_COUNT0, prbsErrorCount);
            retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
            IF_ERR_RETURN_U32(retVal);
        }
        else if (lane == 1)
        {
            halError = talSpiReadByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_PRBS_ERROR_COUNT1), prbsErrorCount);
            retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
            IF_ERR_RETURN_U32(retVal);
        }
        else if (lane == 2)
        {
            halError = talSpiReadByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_PRBS_ERROR_COUNT2), prbsErrorCount);
            retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
            IF_ERR_RETURN_U32(retVal);
        }
        else if (lane == 3)
        {
            halError = talSpiReadByte(device->devHalInfo, (TALISE_ADDR_JESD_DEFRAMER_PRBS_ERROR_COUNT3), prbsErrorCount);
            retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
            IF_ERR_RETURN_U32(retVal);
        }
        else
        {
            return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_READDFRMPRBS_INV_DEFSEL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
        }
    }

    return (uint32_t)retVal;
}

uint32_t TALISE_getDfrmIlasMismatch(taliseDevice_t *device, taliseDeframerSel_t deframerSelect, uint32_t *mismatch, taliseJesd204bLane0Config_t *dfrmCfg, taliseJesd204bLane0Config_t *dfrmIlas)
{
    static const uint8_t LINK_ENABLE_MASK = 0x01;
    static const uint8_t JESD_SYNC_MASK   = 0x10;

    talRecoveryActions_t retVal = TALACT_NO_ACTION;     /* Local api error container                                             */
    adiHalErr_t halError = ADIHAL_OK;       /* Local arm error container                                             */
    uint16_t i = 0;                         /* Local loop counter                                                    */
    uint8_t ilasdata[15] = {0};             /* Local holds lane0 ilas configuration data                             */
    uint8_t cfgdata[15] = {0};              /* Local holds lane0 configuration data                                  */
    uint16_t zeroCheck = 0x0000;            /* Local used for or'ing to determine if lane configuration is all zeros */
    uint16_t ilasAddress = 0;               /* Local used to assemble ilas addresses on the fly                      */
    uint16_t cfgAddress = 0;                /* Local used to assemble cfg addresses on the fly                       */
    uint16_t syncbAddress = 0;              /* Local used to assemble syncB register addresses on the fly            */
    uint8_t syncRegister = 0;               /* Local holds contents of syncB register                                */
    uint16_t cfgAddrArray[15] = {0};        /* Local holds cfg addresses for spiReadBytes to fetch Cfg values        */
    uint16_t ilasAddrArray[15] = {0};       /* Local holds ilas addresses for spiReadBytes to fetch ILAS values      */
    taliseJesd204bLane0Config_t dfrmCfgLocal = {0}; /* Local deframer configuration settings                               */
    taliseJesd204bLane0Config_t dfrmIlasLocal = {0}; /* Local deframer Ilas settings                                       */

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_getDfrmIlasMismatch()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    if (mismatch == NULL)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM, retVal, TALACT_ERR_CHECK_PARAM);        
    }

    *mismatch = 0;

    /* select the deframer to interrogate */
    if (deframerSelect == TAL_DEFRAMER_A)
    {
        ilasAddress = TALISE_ADDR_JESD_DEFRAMER_IP_OBS0_0;
        cfgAddress = TALISE_ADDR_JESD_DEFRAMER_L0_CFG0_0;
        syncbAddress = TALISE_ADDR_JESD_DEFRAMER_CFG_0;
    }
    else if (deframerSelect == TAL_DEFRAMER_B)
    {
        ilasAddress = TALISE_ADDR_JESD_DEFRAMER_IP_OBS0_1;
        cfgAddress = TALISE_ADDR_JESD_DEFRAMER_L0_CFG0_1;
        syncbAddress = TALISE_ADDR_JESD_DEFRAMER_CFG_1;
    }
    else
    {
        retVal = talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                                  TAL_ERR_JESD204B_ILAS_MISMATCH_INVALID_DEFRAMER, retVal,
                                  TALACT_ERR_CHECK_PARAM);
        IF_ERR_RETURN_U32(retVal);
    }

    /* check the deframer for link enable and syncB active */
    halError = talSpiReadByte(device->devHalInfo, syncbAddress, &syncRegister);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    if ((syncRegister & LINK_ENABLE_MASK) == 0)
    {
        retVal = talApiErrHandler(device, TAL_ERRHDL_API_FAIL,
                                  TAL_ERR_JESD204B_ILAS_MISMATCH_NO_ACTIVE_LINK, retVal,
                                  TALACT_ERR_CHECK_PARAM);
        IF_ERR_RETURN_U32(retVal);
    }

    if ((syncRegister & JESD_SYNC_MASK) == 0)
    {
        retVal = talApiErrHandler(device, TAL_ERRHDL_API_FAIL,
                                  TAL_ERR_JESD204B_ILAS_MISMATCH_SYNC_NOT_DETECTED, retVal,
                                  TALACT_ERR_CHECK_PARAM);
        IF_ERR_RETURN_U32(retVal);
    }

    /* if parameter dfrmCfg is null allocation buffer */
    if (dfrmCfg == NULL)
    {
        dfrmCfg = &dfrmCfgLocal;
    }

    /* if parameter dfrmIlas is null allocation buffer */
    if (dfrmIlas == NULL)
    {
        dfrmIlas = &dfrmIlasLocal;
    }

    /* load the cfg and ilas address arrays */
    for (i = 0; i < 11; i++)
    {
        cfgAddrArray[i] = (cfgAddress + i);
        ilasAddrArray[i] = (ilasAddress + i);
    }

    cfgAddrArray[11] = (deframerSelect == TAL_DEFRAMER_A) ? TALISE_ADDR_JESD_DEFRAMER_IP_OBS25_0 : TALISE_ADDR_JESD_DEFRAMER_IP_OBS25_1;
    ilasAddrArray[11] = (deframerSelect == TAL_DEFRAMER_A) ? TALISE_ADDR_JESD_DEFRAMER_IP_OBS13_0 : TALISE_ADDR_JESD_DEFRAMER_IP_OBS13_1;

    cfgAddrArray[12] = (deframerSelect == TAL_DEFRAMER_A) ? TALISE_ADDR_JESD_DEFRAMER_IP_OBS38_0 : TALISE_ADDR_JESD_DEFRAMER_IP_OBS38_1;
    ilasAddrArray[12] = (deframerSelect == TAL_DEFRAMER_A) ? TALISE_ADDR_JESD_DEFRAMER_IP_OBS35_0 : TALISE_ADDR_JESD_DEFRAMER_IP_OBS35_1;

    cfgAddrArray[13] = (deframerSelect == TAL_DEFRAMER_A) ? TALISE_ADDR_JESD_DEFRAMER_IP_OBS39_0 : TALISE_ADDR_JESD_DEFRAMER_IP_OBS39_1;
    ilasAddrArray[13] = (deframerSelect == TAL_DEFRAMER_A) ? TALISE_ADDR_JESD_DEFRAMER_IP_OBS36_0 : TALISE_ADDR_JESD_DEFRAMER_IP_OBS36_1;

    cfgAddrArray[14] = (deframerSelect == TAL_DEFRAMER_A) ? TALISE_ADDR_JESD_DEFRAMER_IP_OBS40_0 : TALISE_ADDR_JESD_DEFRAMER_IP_OBS40_1;
    ilasAddrArray[14] = (deframerSelect == TAL_DEFRAMER_A) ? TALISE_ADDR_JESD_DEFRAMER_IP_OBS37_0 : TALISE_ADDR_JESD_DEFRAMER_IP_OBS37_1;

    for (i = 0; i < 15; i++)
    {
        /* fetch the ilas data items */
        halError = talSpiReadByte(device->devHalInfo, cfgAddrArray[i], &cfgdata[i]);
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);

        /* fetch the cfg data items */
        halError = talSpiReadByte(device->devHalInfo, ilasAddrArray[i], &ilasdata[i]);
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    /* do the zero check of ilas data items */
    zeroCheck = 0x0000;
    for (i = 0; i < 15; i++)
    {
        zeroCheck = zeroCheck | ilasdata[i];
    }

    /* If ILAS configuration is all zeros then lane0 is not running */
    if (zeroCheck == 0x0000)
    {
        retVal = talApiErrHandler(device, TAL_ERRHDL_API_FAIL,
                                  TAL_ERR_JESD204B_ILAS_MISMATCH_NO_ACTIVE_LINK, retVal,
                                  TALACT_ERR_CHECK_PARAM);
        IF_ERR_RETURN_U32(retVal);
    }

    /* loading the structures with the read values for easier reading when doing compares */
    dfrmIlas->DID = ilasdata[0];                 /* jesd_deframer_IP_obs0  */
    dfrmIlas->BID = (ilasdata[1] & 0x0F);        /* jesd_deframer_IP_obs1  */
    dfrmIlas->LID0 = (ilasdata[2] & 0x1F);       /* jesd_deframer_IP_obs2  */
    dfrmIlas->L = (ilasdata[3] & 0x1F);          /* jesd_deframer_IP_obs3  */
    dfrmIlas->SCR = ((ilasdata[3] & 0x80) >> 7); /* jesd_deframer_IP_obs3  */
    dfrmIlas->F = ilasdata[4];                   /* jesd_deframer_IP_obs4  */
    dfrmIlas->K = (ilasdata[5] & 0x1F);          /* jesd_deframer_IP_obs5  */
    dfrmIlas->M = ilasdata[6];                   /* jesd_deframer_IP_obs6  */
    dfrmIlas->N = (ilasdata[7] & 0x1F);          /* jesd_deframer_IP_obs7  */
    dfrmIlas->CS = ((ilasdata[7] & 0xC0) >> 6);  /* jesd_deframer_IP_obs7  */
    dfrmIlas->NP = (ilasdata[8] & 0x1F);         /* jesd_deframer_IP_obs8  */
    dfrmIlas->S = (ilasdata[9] & 0x1F);          /* jesd_deframer_IP_obs9  */
    dfrmIlas->CF = (ilasdata[10] & 0x1F);        /* jesd_deframer_IP_obs10 */
    dfrmIlas->HD = ((ilasdata[10] & 0x80) >> 7); /* jesd_deframer_IP_obs10 */
    dfrmIlas->FCHK0 = ilasdata[11];              /* lane0 Ilas CheckSum    */
    dfrmIlas->FCHK1 = ilasdata[12];              /* lane1 Ilas CheckSum    */
    dfrmIlas->FCHK2 = ilasdata[13];              /* lane2 Ilas CheckSum    */
    dfrmIlas->FCHK3 = ilasdata[14];              /* lane3 Ilas CheckSum    */


    dfrmCfg->DID = cfgdata[0];                  /* jesd_deframer_LO_cfg0       */
    dfrmCfg->BID = (cfgdata[1] & 0x0F);         /* jesd_deframer_LO_cfg1       */
    dfrmCfg->LID0 = (cfgdata[2] & 0x1F);        /* jesd_deframer_LO_cfg2       */
    dfrmCfg->L = (cfgdata[3] & 0x1F);           /* jesd_deframer_LO_cfg3       */
    dfrmCfg->SCR = ((cfgdata[3] & 0x80) >> 7);  /* jesd_deframer_LO_cfg3       */
    dfrmCfg->F = cfgdata[4];                    /* jesd_deframer_LO_cfg4       */
    dfrmCfg->K = (cfgdata[5] & 0x1F);           /* jesd_deframer_LO_cfg5       */
    dfrmCfg->M = cfgdata[6];                    /* jesd_deframer_LO_cfg6       */
    dfrmCfg->N = (cfgdata[7] & 0x1F);           /* jesd_deframer_LO_cfg7       */
    dfrmCfg->CS = ((cfgdata[7] & 0xC0) >> 6);   /* jesd_deframer_LO_cfg7       */
    dfrmCfg->NP = (cfgdata[8] & 0x1F);          /* jesd_deframer_LO_cfg8       */
    dfrmCfg->S = (cfgdata[9] & 0x1F);           /* jesd_deframer_LO_cfg9       */
    dfrmCfg->CF = (cfgdata[10] & 0x1F);         /* jesd_deframer_LO_cfg10      */
    dfrmCfg->HD = ((cfgdata[10] & 0x80) >> 7);  /* jesd_deframer_LO_cfg10      */
    dfrmCfg->FCHK0 = cfgdata[11];               /* lane0 Cfg Computed CheckSum */
    dfrmCfg->FCHK1 = cfgdata[12];               /* lane1 Cfg Computed CheckSum */
    dfrmCfg->FCHK2 = cfgdata[13];               /* lane2 Cfg Computed CheckSum */
    dfrmCfg->FCHK3 = cfgdata[14];               /* lane3 Cfg Computed CheckSum */


    /* performing ILAS mismatch check */
    *mismatch = 0x00000000;
    if (dfrmIlas->DID != dfrmCfg->DID)
    {
        *mismatch |= 0x00000001;
    }

    if (dfrmIlas->BID != dfrmCfg->BID)
    {
        *mismatch |= 0x00000002;
    }

    if (dfrmIlas->LID0 != dfrmCfg->LID0)
    {
        *mismatch |= 0x00000004;
    }

    if (dfrmIlas->L != dfrmCfg->L)
    {
        *mismatch |= 0x00000008;
    }

    if (dfrmIlas->SCR != dfrmCfg->SCR)
    {
        *mismatch |= 0x00000010;
    }

    if (dfrmIlas->F != dfrmCfg->F)
    {
        *mismatch |= 0x00000020;
    }

    if (dfrmIlas->K != dfrmCfg->K)
    {
        *mismatch |= 0x00000040;
    }

    if (dfrmIlas->M != dfrmCfg->M)
    {
        *mismatch |= 0x00000080;
    }

    if (dfrmIlas->N != dfrmCfg->N)
    {
        *mismatch |= 0x00000100;
    }

    if (dfrmIlas->CS != dfrmCfg->CS)
    {
        *mismatch |= 0x00000200;
    }

    if (dfrmIlas->NP != dfrmCfg->NP)
    {
        *mismatch |= 0x00000400;
    }

    if (dfrmIlas->S != dfrmCfg->S)
    {
        *mismatch |= 0x00000800;
    }

    if (dfrmIlas->CF != dfrmCfg->CF)
    {
        *mismatch |= 0x00001000;
    }

    if (dfrmIlas->HD != dfrmCfg->HD)
    {
        *mismatch |= 0x00002000;
    }

    /* verify lane ilas checksums equal lane computed checksums */
    for (i = 11; i < 15; i++)
    {
        /* if ilas checksum equal zero then the lane is inactive so suppress lane checksum mismatch flag */
        if ((ilasdata[i] != cfgdata[i]) && (ilasdata[i] != 0x00))
        {
            *mismatch |= (0x00004000 << (i - 11));

        }
    }

    return (uint32_t)retVal;
}

uint32_t TALISE_setDfrmIrqMask(taliseDevice_t *device, taliseDeframerSel_t deframerSelect, uint16_t irqMask)
{
    static const uint8_t ERROR_COUNTERS_ENABLE_MASK = 0x3F;
    static const uint8_t IRQ_BIT8_MASK = 0x80;

    uint8_t enCount = 0;
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t dataArray[2] = {0};
    uint16_t addrArray[2] = {0};

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_setDfrmIrqMask()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    /* param range check */
    if ((deframerSelect != TAL_DEFRAMER_A) && (deframerSelect != TAL_DEFRAMER_B))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                                          TAL_ERR_SETDFRMIRQMASK_INV_DEFRAMERSEL_PARAM, retVal,
                                          TALACT_ERR_CHECK_PARAM);
    }

    if (deframerSelect == TAL_DEFRAMER_A)
    {
        addrArray[0] = TALISE_ADDR_JESD_DEFRAMER_IP_CFG2_0;
        addrArray[1] = TALISE_ADDR_JESD_DEFRAMER_IP_CFG3_0;
    }
    else
    {
        addrArray[0] = TALISE_ADDR_JESD_DEFRAMER_IP_CFG2_1;
        addrArray[1] = TALISE_ADDR_JESD_DEFRAMER_IP_CFG3_1;
    }

    /* fetch the contents of the enable counters register where bit7 is IRQ[8:8] readmodifywrite operation*/
    halError = talSpiReadByte(device->devHalInfo, addrArray[1], &enCount);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    dataArray[0] = (uint8_t)irqMask;
    dataArray[1] = (enCount & ERROR_COUNTERS_ENABLE_MASK) | IRQ_BIT8_MASK; /* BIT8 CMM IRQ is disabled to correct BUG */

    halError = talSpiWriteBytes(device->devHalInfo, &addrArray[0], &dataArray[0], 2);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    return ((uint32_t)retVal);
}


uint32_t TALISE_getDfrmIrqMask(taliseDevice_t *device, taliseDeframerSel_t deframerSelect, uint16_t *irqMask)
{
    static const uint8_t IRQ_BIT8_MASK = 0x80;

    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint8_t dataArray[2] = {0};
    uint16_t addrArray[2] = {0};

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_getDfrmIrqMask()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    /* param range check */
    if (irqMask == NULL)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                                          TAL_ERR_GETDFRMIRQMASK_NULL_IRQMASK_PARAM, retVal,
                                          TALACT_ERR_CHECK_PARAM);
    }

    /* param range check */
    if ((deframerSelect != TAL_DEFRAMER_A) &&
        (deframerSelect != TAL_DEFRAMER_B))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                                          TAL_ERR_GETDFRMIRQMASK_INV_DEFRAMERSELECT_PARAM, retVal,
                                          TALACT_ERR_CHECK_PARAM);
    }

    if (deframerSelect == TAL_DEFRAMER_A)
    {
        addrArray[0] = TALISE_ADDR_JESD_DEFRAMER_IP_CFG2_0;
        addrArray[1] = TALISE_ADDR_JESD_DEFRAMER_IP_CFG3_0;
    }
    else
    {
        addrArray[0] = TALISE_ADDR_JESD_DEFRAMER_IP_CFG2_1;
        addrArray[1] = TALISE_ADDR_JESD_DEFRAMER_IP_CFG3_1;
    }

    /* fetch IRQ mask low */
    halError = talSpiReadByte(device->devHalInfo, addrArray[0], &dataArray[0]);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* fetch IRQ mask high */
    halError = talSpiReadByte(device->devHalInfo, addrArray[1], &dataArray[1]);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    *irqMask = ((uint16_t)(dataArray[1] & IRQ_BIT8_MASK)) << 1 | ((uint16_t)dataArray[0]);

    return ((uint32_t)retVal);
}

uint32_t TALISE_getDfrmIrqSource(taliseDevice_t *device, taliseDeframerSel_t deframerSelect, uint16_t *irqSourceValue)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint16_t irqVector[8] = {0};
    uint8_t dataArray[8] = {0};

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_getDfrmIrqSource()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    /* param range check */
    if (irqSourceValue == NULL)
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                 TAL_ERR_GETDFRMIRQSRC_NULL_STATUS_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* param range check */
    if ((deframerSelect != TAL_DEFRAMER_A) &&
        (deframerSelect != TAL_DEFRAMER_B))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                   TAL_ERR_GETDFRMIRQSRC_INV_DEFRAMERSEL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    if (deframerSelect == TAL_DEFRAMER_A)
    {
        irqVector[0] = TALISE_ADDR_JESD_DEFRAMER_IP_OBS14_0;
        irqVector[1] = TALISE_ADDR_JESD_DEFRAMER_IP_OBS15_0;
        irqVector[2] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_DET_LAT_BUF_0;
        irqVector[3] = TALISE_ADDR_JESD_DEFRAMER_SYSREF_CFG2_0;
        irqVector[4] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE0;
        irqVector[5] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE1;
        irqVector[6] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE2;
        irqVector[7] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE3;
    }
    else
    {
        irqVector[0] = TALISE_ADDR_JESD_DEFRAMER_IP_OBS14_1;
        irqVector[1] = TALISE_ADDR_JESD_DEFRAMER_IP_OBS15_1;
        irqVector[2] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_DET_LAT_BUF_1;
        irqVector[3] = TALISE_ADDR_JESD_DEFRAMER_SYSREF_CFG2_1;
        irqVector[4] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE0;
        irqVector[5] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE1;
        irqVector[6] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE2;
        irqVector[7] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE3;
    }

    /* fetch IRQ sources */
    halError = talSpiReadBytes(device->devHalInfo, &irqVector[0], &dataArray[0], 8);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    *irqSourceValue = ((uint16_t)(dataArray[7] & 0x01) << 14) | (((uint16_t)(dataArray[6] & 0x01) << 13) |
                     (((uint16_t)(dataArray[5] & 0x01) << 12) | (((uint16_t)(dataArray[4] & 0x01) << 11) |
                     (((uint16_t)(dataArray[3] & 0x02) << 9) | (((uint16_t)(dataArray[2] & 0x01) << 9) |
                     (((uint16_t)(dataArray[1] & 0x01) << 8) | dataArray[0]))))));

    return((uint32_t)retVal);
}

uint32_t TALISE_clearDfrmIrq(taliseDevice_t *device, taliseDeframerSel_t deframerSelect)
{
    static const uint8_t IRQ_BIT8_MASK = 0x80;

    uint8_t enCount = 0;
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    talRecoveryActions_t retValWarn = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint16_t irqVector[8] = {0};
    uint8_t dataArray[8] = {0};
    uint16_t irqMask = 0;
    int16_t i = 0;
    uint8_t irqSource = 0;
    uint16_t irqSourceAddr = TALISE_ADDR_JESD_DEFRAMER_IP_OBS14_0;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_clearDfrmIrq()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    retValWarn = retVal;

    /* param range check */
    if ((deframerSelect != TAL_DEFRAMER_A) &&
        (deframerSelect != TAL_DEFRAMER_B))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                                          TAL_ERR_CLRDFRMIRQ_INV_DEFRAMERSEL_PARAM, retVal,
                                          TALACT_ERR_CHECK_PARAM);
    }

    if (deframerSelect == TAL_DEFRAMER_A)
    {
        irqVector[0] = TALISE_ADDR_JESD_DEFRAMER_IP_CFG2_0;
        irqVector[1] = TALISE_ADDR_JESD_DEFRAMER_IP_CFG3_0;
        irqVector[2] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_DET_LAT_BUF_0;
        irqVector[3] = TALISE_ADDR_JESD_DEFRAMER_SYSREF_CFG2_0;
        irqVector[4] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE0;
        irqVector[5] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE1;
        irqVector[6] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE2;
        irqVector[7] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE3;

        irqSourceAddr = TALISE_ADDR_JESD_DEFRAMER_IP_OBS14_0;
    }
    else
    {
        irqVector[0] = TALISE_ADDR_JESD_DEFRAMER_IP_CFG2_1;
        irqVector[1] = TALISE_ADDR_JESD_DEFRAMER_IP_CFG3_1;
        irqVector[2] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_DET_LAT_BUF_1;
        irqVector[3] = TALISE_ADDR_JESD_DEFRAMER_SYSREF_CFG2_1;
        irqVector[4] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE0;
        irqVector[5] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE1;
        irqVector[6] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE2;
        irqVector[7] = TALISE_ADDR_JESD_DEFRAMER_PTR_DBG_LANE3;

        irqSourceAddr = TALISE_ADDR_JESD_DEFRAMER_IP_OBS14_1;
    }

    retVal = (talRecoveryActions_t)TALISE_getDfrmIrqMask(device, deframerSelect, &irqMask);
    IF_ERR_RETURN_U32(retVal);

    /* fetch the contents of the deframer IRQ source */
    halError = talSpiReadByte(device->devHalInfo, irqSourceAddr, &irqSource);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* fetch the contents of the enable counters register where bit7 is IRQ[8:8] readmodifywrite operation*/
    halError = talSpiReadByte(device->devHalInfo, irqVector[1], &enCount);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    dataArray[0] = ((~irqSource) & 0xFF);
    dataArray[1] = (enCount | IRQ_BIT8_MASK);

    /* Clear the IRQ[7:0] and IRQ[8:8] */
    halError = talSpiWriteBytes(device->devHalInfo, &irqVector[0], &dataArray[0], 2);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    halError = talSpiWriteField(device->devHalInfo, irqVector[3], dataArray[3], 0x02, 1);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* Clear the remain static IRQs */
    for (i = 4; i <= 7; i++)
    {
        if (dataArray[i] > 0)
        {
            halError = talSpiWriteByte(device->devHalInfo, irqVector[i], 0x00);
            retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
            IF_ERR_RETURN_U32(retVal);
        }
    }

    /* restore orignal irqmask */
    halError = talSpiWriteByte(device->devHalInfo, irqVector[0], (uint8_t)(irqMask & 0x00FF));
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* disable CMM IRQ */
    halError = talSpiWriteField(device->devHalInfo, irqVector[1], 1, IRQ_BIT8_MASK, 7);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN_U32(retVal);

    /* If higher priority retVal has no error, allow possible lower priority warning to be returned */
    if (retVal == TALACT_NO_ACTION)
    {
        retVal = retValWarn;
    }

    return ((uint32_t)retVal);
}

talRecoveryActions_t talFindDfrmrLaneCntErr(taliseDevice_t *device,  taliseDeframerSel_t deframer, int32_t *deframerInputsMask)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;

    uint8_t msByte = 0;
    uint8_t lsByte = 0;
    uint8_t cntrResetMask = 0;
    uint16_t deframerTcrAddress0 = 0;
    uint16_t deframerTcrAddress1 = 0;
    uint16_t deframerEcntRstAddress0 = 0;
    uint16_t deframerEcntRstAddress1 = 0;

    static const uint16_t ECNT_TCH_LANE0_MASK = 0x0007;
    static const uint16_t ECNT_TCH_LANE1_MASK = 0x0038;
    static const uint16_t ECNT_TCH_LANE2_MASK = 0x0007;
    static const uint16_t ECNT_TCH_LANE3_MASK = 0x0038;

    if (deframer == TAL_DEFRAMER_A)
    {
        deframerEcntRstAddress0 = TALISE_ADDR_JESD_DEFRAMER_IP_CFG5_0;
        deframerEcntRstAddress1 = TALISE_ADDR_JESD_DEFRAMER_IP_CFG6_0;
        deframerTcrAddress0 = TALISE_ADDR_JESD_DEFRAMER_IP_OBS23_0;
        deframerTcrAddress1 = TALISE_ADDR_JESD_DEFRAMER_IP_OBS24_0;

    }
    else if (deframer == TAL_DEFRAMER_B)
    {
        deframerEcntRstAddress0 = TALISE_ADDR_JESD_DEFRAMER_IP_CFG5_1;
        deframerEcntRstAddress1 = TALISE_ADDR_JESD_DEFRAMER_IP_CFG6_1;
        deframerTcrAddress0 = TALISE_ADDR_JESD_DEFRAMER_IP_OBS23_1;
        deframerTcrAddress1 = TALISE_ADDR_JESD_DEFRAMER_IP_OBS24_1;
    }
    else
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                                TAL_ERR_TALFINDDFRMRLANECNTERROR_INV_DEFRAMERSEL_PARAM, retVal,
                                TALACT_ERR_CHECK_PARAM);
    }

    if (deframerInputsMask == NULL)
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                                TAL_ERR_TALFINDDFRMRLANECNTERROR_NULL_PARAM, retVal,
                                TALACT_ERR_CHECK_PARAM);
    }

    /* Read the TCR registers */
    halError = talSpiReadByte(device->devHalInfo, deframerTcrAddress1, &msByte);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    halError = talSpiReadByte(device->devHalInfo, deframerTcrAddress0, &lsByte);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    /* Deframer input 0 */
    *deframerInputsMask = 0;
    cntrResetMask = (lsByte & ECNT_TCH_LANE0_MASK);
    if (cntrResetMask > 0)
    {
        *deframerInputsMask |= 0x01;
    }

    /* Deframer input 1 */
    cntrResetMask = (lsByte & ECNT_TCH_LANE1_MASK);
    if (cntrResetMask > 0)
    {
        *deframerInputsMask |= 0x02;
    }

    /* Deframer input 2 */
    cntrResetMask = (msByte & ECNT_TCH_LANE2_MASK);
    if (cntrResetMask > 0)
    {
        *deframerInputsMask |= 0x04;
    }

    /* Deframer input 3 */
    cntrResetMask = (msByte & ECNT_TCH_LANE3_MASK);
    if (cntrResetMask > 0)
    {
        *deframerInputsMask |= 0x08;
    }

    /* clear the error counter */
    halError = talSpiWriteByte(device->devHalInfo, deframerEcntRstAddress0, 0x00);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    /* clear the error counter */
    halError = talSpiWriteByte(device->devHalInfo, deframerEcntRstAddress1, 0x00);
    retVal = talApiErrHandler(device,TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    return (retVal);
}

talRecoveryActions_t talFindDfrmrLaneErr(taliseDevice_t *device,  uint32_t dfrmErrAddress, uint8_t nibbleToUse, int32_t *deframerInputsMask)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;

    uint8_t dfrmErrMask = 0; /* 4 bits in either upper /lower nibble that describe the lanes an error occurred on */

    static const uint8_t HIGH = 1;

    if (deframerInputsMask == NULL)
    {
        return talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                                TAL_ERR_TALFINDDFRMRLANEERROR_NULL_PARAM, retVal,
                                TALACT_ERR_CHECK_PARAM);
    }

    /* Read error flags from requested deframer register address */
    halError = talSpiReadByte(device->devHalInfo, dfrmErrAddress, &dfrmErrMask);
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
    IF_ERR_RETURN(retVal);

    if (nibbleToUse >= HIGH)
    {
        /* Grab lane error mask from upper 4 bits in each register */
        *deframerInputsMask = ((dfrmErrMask >> 4) & 0x0F);
    }
    else
    {
        /* Grab lane error mask from lower 4 bits in each register */
        *deframerInputsMask = (dfrmErrMask & 0x0F);
    }

    return (retVal);
}

uint32_t TALISE_framerSyncbToggle(taliseDevice_t *device, taliseFramerSel_t framerSel)
{
    talRecoveryActions_t retVal = TALACT_NO_ACTION;
    talRecoveryActions_t retValWarn = TALACT_NO_ACTION;
    adiHalErr_t halError = ADIHAL_OK;
    uint16_t framerAddrOffset = 0;
    uint8_t framerCfg0Value = 0;

    static const uint8_t FORCE_SYNCB_HIGH = 0x0C;
    static const uint8_t FORCE_SYNCB_LOW = 0x04;
    static const uint8_t FORCE_SYNCB_CLEAR_BITMASK = 0xF3;

#if TALISE_VERBOSE
    halError = talWriteToLog(device->devHalInfo, ADIHAL_LOG_MSG, TAL_ERR_OK, "TALISE_framerSyncbToggle()\n");
    retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_LOG, halError, retVal, TALACT_WARN_RESET_LOG);
#endif

    if ((framerSel != TAL_FRAMER_A) &&
        (framerSel != TAL_FRAMER_B) &&
        (framerSel != TAL_FRAMER_A_AND_B))
    {
        return (uint32_t)talApiErrHandler(device, TAL_ERRHDL_INVALID_PARAM,
                TAL_ERR_FRAMERSYSREFTOGGLE_INV_FRAMERSEL_PARAM, retVal, TALACT_ERR_CHECK_PARAM);
    }

    /* Save possible warning from logging until end of function */
    retValWarn = retVal;

    if ((framerSel == TAL_FRAMER_A) ||
        (framerSel == TAL_FRAMER_A_AND_B))
    {
        framerAddrOffset = 0;

        /* Perform Read/modify/write to prevent changing other bits in the register */
        halError = talSpiReadByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG_0 + framerAddrOffset), &framerCfg0Value);
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);

        framerCfg0Value &= FORCE_SYNCB_CLEAR_BITMASK; /* Clear bits [3:2] */
        framerCfg0Value |= FORCE_SYNCB_HIGH; /* Set reg [3:2] = b11 - force SYNCB high */
        halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG_0 + framerAddrOffset), framerCfg0Value);
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);

        framerCfg0Value &= FORCE_SYNCB_CLEAR_BITMASK; /* Clear bits [3:2] */
        framerCfg0Value |= FORCE_SYNCB_LOW; /* Set reg [3:2] = b01 - force SYNCB low */
        halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG_0 + framerAddrOffset), framerCfg0Value);
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);

        framerCfg0Value &= FORCE_SYNCB_CLEAR_BITMASK; /* Clear bits [3:2], Set reg [3:2] = b00 - disable force of SYNCB */
        halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG_0 + framerAddrOffset), framerCfg0Value);
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    if ((framerSel == TAL_FRAMER_B) ||
        (framerSel == TAL_FRAMER_A_AND_B))
    {
        framerAddrOffset = TALISE_JESD_FRAMERB_OFFSET;

        /* Perform Read/modify/write to prevent changing other bits in the register */
        halError = talSpiReadByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG_0 + framerAddrOffset), &framerCfg0Value);
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);

        framerCfg0Value &= FORCE_SYNCB_CLEAR_BITMASK; /* Clear bits [3:2] */
        framerCfg0Value |= FORCE_SYNCB_HIGH; /* Set reg [3:2] = b11 - force SYNCB high */
        halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG_0 + framerAddrOffset), framerCfg0Value);
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);

        framerCfg0Value &= FORCE_SYNCB_CLEAR_BITMASK; /* Clear bits [3:2] */
        framerCfg0Value |= FORCE_SYNCB_LOW; /* Set reg [3:2] = b01 - force SYNCB low */
        halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG_0 + framerAddrOffset), framerCfg0Value);
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);

        framerCfg0Value &= FORCE_SYNCB_CLEAR_BITMASK; /* Clear bits [3:2], Set reg [3:2] = b00 - disable force of SYNCB */
        halError = talSpiWriteByte(device->devHalInfo, (TALISE_ADDR_JESD_FRAMER_CFG_0 + framerAddrOffset), framerCfg0Value);
        retVal = talApiErrHandler(device, TAL_ERRHDL_HAL_SPI, halError, retVal, TALACT_ERR_RESET_SPI);
        IF_ERR_RETURN_U32(retVal);
    }

    /* If higher priority retVal has no error, allow possible lower priority warning to be returned */
    if (retVal == TALACT_NO_ACTION)
    {
        retVal = retValWarn;
    }

    return (uint32_t)retVal;
}

